package com.guet; // 声明包名

import javax.imageio.ImageIO; // 导入用于处理图片的包
import java.awt.event.*; // 导入用于处理事件的包
import java.io.*; // 导入用于处理输入输出的包
import javax.swing.*; // 导入用于创建图形用户界面的包
import java.awt.*; // 导入用于图形界面的包
import java.awt.image.BufferedImage; // 导入用于处理缓冲图像的包
import java.util.*; // 导入用于集合框架的包
import java.util.List; // 导入用于列表的包

import com.sun.speech.freetts.Voice; // 导入用于语音合成的包
import com.sun.speech.freetts.VoiceManager; // 导入用于管理语音合成的包

// 主类，包含主窗体
public class MyJFrame {
    static MyShapesPanel drawPanel; // 静态成员，绘图面板

    // 构造方法
    public MyJFrame() {
        drawPanel = new MyShapesPanel(); // 初始化绘图面板
        new MyGraphics(drawPanel); // 创建主窗体，并将绘图面板添加到窗体中
    }
}

// 画板类，实现绘图功能
class MyShapesPanel extends JPanel implements Runnable {
    public algorithm alg = new algorithm(); // 创建算法对象
    public MGraph mgraph = alg.mGraph; // 获取图对象
    public JTextArea messageText; // 用于显示导航信息的文本域
    public final List<Integer> shortest = new LinkedList<>(); // 用于存储最短路径的列表
    public final Map<Integer, vexsinfo> showPoints = new HashMap<>(); // 用于存储需要显示的点的映射
    int run = 0; // 标记是否运行
    int id; // 当前节点ID
    int x; // 当前X坐标
    int y; // 当前Y坐标
    int speedUp = 1; // 速度加倍倍数
    int every = 1; // 用于显示标签中的速度信息
    int showAll = 0; // 标记是否显示所有节点
    String currentTime = "当前时间"; // 当前时间
    String goWay = "步行"; // 当前交通方式
    BufferedImage bufImg; // 缓冲图像
    BufferedImage walkIcon; // 步行图标
    BufferedImage cycleIcon; // 骑行图标
    BufferedImage carIcon; // 驾车图标
    int imgWidth; // 图像宽度
    int imgHeight; // 图像高度

    private TextToSpeech tts = new TextToSpeech(); // 创建TextToSpeech对象

    // 构造方法
    public MyShapesPanel() {
        setBackground(Color.white); // 设置背景颜色为白色
        try {
            File file = new File("resources/guet.jpg"); // 加载背景图片
            bufImg = ImageIO.read(file); // 读取图片文件
            imgWidth = bufImg.getWidth(); // 获取图片宽度
            imgHeight = bufImg.getHeight(); // 获取图片高度

            walkIcon = ImageIO.read(new File("resources/walk_icon.png")); // 读取步行图标
            cycleIcon = ImageIO.read(new File("resources/cycle_icon.png")); // 读取骑行图标
            carIcon = ImageIO.read(new File("resources/car_icon.png")); // 读取驾车图标
        } catch (IOException e) {
            System.out.println("图片加载出错"); // 捕获并打印异常信息
        }
    }

    // 重写paintComponent方法，用于自定义绘图
    public void paintComponent(Graphics g) {
        super.paintComponent(g); // 调用父类的paintComponent方法
        if (bufImg != null) {
            g.drawImage(bufImg, 0, 0, this); // 绘制背景图片
        }
        // 绘制各个结点的标点
        g.setColor(Color.red); // 设置颜色为红色
        for (vexsinfo v : showPoints.values()) {
            g.setFont(new Font("黑体", Font.CENTER_BASELINE, 10)); // 设置字体
            g.setColor(new Color(196, 107, 47)); // 设置颜色
            g.fillOval(v.logicx, v.logicy, 10, 10); // 绘制节点
            g.setColor(Color.black); // 设置颜色为黑色
            g.drawLine(v.logicx + 5, v.logicy - 3, v.logicx + 20, v.logicy - 20); // 绘制线条
            g.drawString(v.name, v.logicx + 15, v.logicy - 20); // 绘制节点名称
            g.setColor(Color.BLUE); // 设置颜色为蓝色
        }
        if (showAll == 1) { // 如果标记为显示所有节点
            for (vexsinfo v : mgraph.vexs.values()) {
                int[] a = {v.top, v.bottom, v.left, v.right}; // 获取节点的四个方向
                for (int j = 0; j < 4; j++) {
                    if (a[j] == -1) continue; // 如果方向无效，跳过
                    ((Graphics2D) g).setStroke(new BasicStroke(1.0f)); // 设置线条粗细
                    g.setColor(Color.BLUE); // 设置颜色为蓝色
                    vexsinfo v1 = mgraph.vexs.get(a[j]); // 获取相邻节点的信息
                    g.drawLine(v1.logicx + 3, v1.logicy + 3, v.logicx + 3, v.logicy + 3); // 绘制相邻节点之间的线条
                    int midX = (v1.logicx + v.logicx) / 2; // 计算中点X坐标
                    int midY = (v1.logicy + v.logicy) / 2; // 计算中点Y坐标
                    g.setFont(new Font("黑体", Font.BOLD, 8)); // 设置字体
                    g.setColor(Color.red); // 设置颜色为红色
                    if (mgraph.arcs[v1.id][v.id] != 0) g.drawString(mgraph.arcs[v1.id][v.id] + "", midX - 5, midY); // 绘制距离
                }
            }
        }
        if (shortest.size() != 0) { // 如果有最短路径
            Iterator<Integer> it = shortest.iterator(); // 创建迭代器
            int start = 0; // 起点ID
            while (it.hasNext()) { // 遍历最短路径
                int end = it.next(); // 终点ID
                if (start == 0) {
                    start = end;
                    continue;
                }
                ((Graphics2D) g).setStroke(new BasicStroke(3.0f)); // 设置线条粗细
                g.setColor(Color.BLUE); // 设置颜色为蓝色
                vexsinfo v1 = mgraph.vexs.get(start); // 获取起点信息
                vexsinfo v2 = mgraph.vexs.get(end); // 获取终点信息
                g.drawLine(v1.logicx + 3, v1.logicy + 3, v2.logicx + 3, v2.logicy + 3); // 绘制路径
                int midX = (v1.logicx + v2.logicx) / 2; // 计算中点X坐标
                int midY = (v1.logicy + v2.logicy) / 2; // 计算中点Y坐标
                g.setFont(new Font("黑体", Font.BOLD, 8)); // 设置字体
                g.setColor(Color.red); // 设置颜色为红色
                if (mgraph.arcs[v1.id][v2.id] != 0) g.drawString(mgraph.arcs[v1.id][v2.id] + "", midX - 5, midY); // 绘制距离
                start = end; // 更新起点
            }
        }
        if (run == 1) { // 如果标记为运行状态
            vexsinfo v = mgraph.vexs.get(id); // 获取当前节点信息
            ((Graphics2D) g).setStroke(new BasicStroke(3.0f)); // 设置线条粗细
            g.setColor(Color.BLUE); // 设置颜色为蓝色
            g.drawLine(v.logicx + 3, v.logicy + 3, x + 3, y + 3); // 绘制当前节点到目标节点的线条
            BufferedImage icon; // 图标
            switch (goWay) { // 根据交通方式选择图标
                case "步行":
                    icon = walkIcon;
                    break;
                case "骑行":
                    icon = cycleIcon;
                    break;
                case "驾车":
                    icon = carIcon;
                    break;
                case "步行+骑行":
                    icon = walkIcon; // 使用步行图标
                    break;
                case "步行+驾车":
                    icon = walkIcon; // 使用步行图标
                    break;
                default:
                    icon = walkIcon;
            }
            if (icon != null) { // 如果图标不为空
                int iconWidth = 30; // 图标宽度
                int iconHeight = 30; // 图标高度
                g.drawImage(icon, x - iconWidth / 2, y - iconHeight / 2, iconWidth, iconHeight, null); // 绘制图标
            } else {
                g.fillOval(x, y, 8, 8); // 绘制节点
            }
        }
    }

    // 绘制两点之间的路径
    public void towPointDrawLine(List<Integer> ids) {
        if (ids == null || ids.isEmpty()) { // 如果路径为空或未找到
            JOptionPane.showMessageDialog(null, "路径无效：路径为空或未找到。"); // 弹出提示框
            return;
        }
        shortest.clear(); // 清空最短路径
        showPoints.get(mgraph.vexs.get(ids.get(0))); // 获取起点
        showPoints.get(mgraph.vexs.get(ids.get(ids.size() - 1))); // 获取终点
        shortest.addAll(ids); // 添加路径
        repaint(); // 重绘面板
    }

    // 停止模拟运行
    public void stopSimulation() {
        run = 0; // 标记为停止状态
        stopSpeech(); // 停止语音播报
    }

    // 停止语音播报的方法
    private void stopSpeech() {
        tts.deallocate(); // 释放TTS资源
    }

    // 重写run方法，用于模拟运行
    @Override
    public void run() {
        run = 1; // 标记为运行状态
        int Distance = alg.getListIdsDistance(shortest); // 获取总路线长度
        int allTime = 0; // 总时间
        int currentP = shortest.size() - 1; // 当前点索引
        int vexSid = shortest.get(currentP--); // 当前节点ID
        int vexPid = shortest.get(currentP--); // 前一个节点ID
        int speed = (int) alg.getSpeed(goWay, currentTime, vexSid, vexPid); // 获取速度
        vexsinfo vexP = mgraph.vexs.get(vexPid); // 获取前一个节点信息
        vexsinfo vexS = mgraph.vexs.get(vexSid); // 获取当前节点信息
        tts.speak("Virtual motion started"); // 语音播报开始
        while (currentP >= -1 && run == 1) { // 模拟运行
            shortest.remove(currentP + 2); // 移除当前点
            double x = vexS.logicx; // 当前X坐标
            double y = vexS.logicy; // 当前Y坐标
            double dx, dy; // X和Y方向的增量
            int t = mgraph.arcs[vexSid][vexPid] / speed; // 计算到下一个节点的时间
            if (vexS.logicy < vexP.logicy) {
                dy = (vexP.logicy - vexS.logicy) * 1.0 / t; // 计算Y方向的增量
            } else dy = (vexS.logicy - vexP.logicy) * (-1.0) / t;
            if (vexS.logicx < vexP.logicx) {
                dx = (vexP.logicx - vexS.logicx) * 1.0 / t; // 计算X方向的增量
            } else dx = (vexS.logicx - vexP.logicx) * (-1.0) / t;
            this.id = vexPid; // 更新当前节点ID
            int speedUpTemp = speedUp; // 临时速度加倍倍数
            int s = mgraph.arcs[vexSid][vexPid]; // 获取当前段的距离
            for (int i = 1; i <= t / speedUpTemp + 1 && Distance > 0; i++, allTime += speedUpTemp) {
                if (Distance - speed * speedUpTemp > 0) Distance -= speed * speedUpTemp; // 更新剩余距离
                if (x != vexP.logicx) x += dx * speedUpTemp; // 更新X坐标
                if (y != vexP.logicy) y += dy * speedUpTemp; // 更新Y坐标
                this.x = (int) x; // 更新当前X坐标
                this.y = (int) y; // 更新当前Y坐标
                messageText.setText("已用时:" + allTime + "s , 剩余路程:" + Distance + "m\n" +
                        "当前速度: " + speed * speedUpTemp + "m/" + every + "s\n" +
                        "你目前位于:" + vexS.name + "与" + vexP.name + "的路线上" + ((vexP.croded_level == 1.0F) ? "" : "(当前时刻拥挤路段)")); // 更新信息文本
                // 语音播报当前速度和位置
                String spokenText = String.format("Current speed: %d meters per second. You are currently on the road between %s and %s", speed * speedUpTemp, vexS.name, vexP.name);
                tts.speak(spokenText); // 语音播报
                repaint(); // 重绘面板
                try {
                    Thread.sleep(1000 / speedUpTemp); // 休眠
                } catch (InterruptedException e) {
                    e.printStackTrace(); // 打印异常信息
                }
                if (speedUpTemp != speedUp) { // 如果速度加倍倍数改变
                    s -= speedUpTemp * i * speed; // 更新剩余距离
                    speedUpTemp = speedUp; // 更新临时速度加倍倍数
                    t = s / speed; // 计算剩余时间
                    i = 0; // 重置计数器
                }
            }
            vexS = vexP; // 更新当前节点信息
            vexSid = vexS.id; // 更新当前节点ID
            if (currentP == -1) { // 如果到达终点
                JOptionPane.showMessageDialog(null, "你已到达" + vexP.name); // 弹出提示框
                break;
            }
            vexP = mgraph.vexs.get(shortest.get(currentP--)); // 获取下一个节点信息
            vexPid = vexP.id; // 更新前一个节点ID
        }
        tts.speak("Virtual motion stopped"); // 语音播报停止
        run = 0; // 标记为停止状态
    }


    // 内部类，用于处理TTS功能
    private class TextToSpeech {
        private static final String VOICE_NAME = "kevin16"; // 英语语音包名称
        private Voice voice; // 语音对象

        // 构造方法
        public TextToSpeech() {
            System.setProperty("freetts.voices", "com.sun.speech.freetts.en.us.cmu_us_kal.KevinVoiceDirectory"); // 设置英语语音包路径
            voice = VoiceManager.getInstance().getVoice(VOICE_NAME); // 获取语音对象

            if (voice == null) { // 如果找不到语音
                System.err.println("Cannot find a voice named " + VOICE_NAME + ". Please specify a different voice."); // 打印错误信息
                return;
            }

            voice.allocate(); // 分配语音资源
            // 调整音色、语速和音量
            voice.setPitch(130); // 设置音调
            voice.setRate(130); // 设置语速
            voice.setVolume(3); // 设置音量
        }

        // 语音播报文本
        public void speak(String text) {
            if (voice != null) {
                voice.speak(text); // 播报文本
            }
        }

        // 释放语音资源
        public void deallocate() {
            if (voice != null) {
                voice.deallocate(); // 释放资源
            }
        }
    }
}

// 主窗体类
class MyGraphics extends JFrame {
    // 构造方法
    public MyGraphics(MyShapesPanel drawPanel) {
        getContentPane().add(drawPanel); // 将绘图面板添加到窗体中
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // 设置关闭操作
        setLocation(100, 50); // 设置窗体位置
        setSize(drawPanel.imgWidth, drawPanel.imgHeight); // 设置窗体大小
        setTitle("校园导航系统"); // 设置窗体标题

        JMenuBar jmenubar = new JMenuBar(); // 创建菜单栏
        JMenu navigation = new JMenu("导航"); // 创建导航菜单
        navigation.setFont(new Font("黑体", Font.BOLD, 16)); // 设置字体
        jmenubar.add(navigation); // 添加导航菜单到菜单栏
        JMenu introduce = new JMenu("地点介绍"); // 创建地点介绍菜单
        introduce.setFont(new Font("黑体", Font.BOLD, 16)); // 设置字体
        jmenubar.add(introduce); // 添加地点介绍菜单到菜单栏
        JMenu root = new JMenu("管理员端"); // 创建管理员端菜单
        root.setFont(new Font("黑体", Font.BOLD, 16)); // 设置字体
        jmenubar.add(root); // 添加管理员端菜单到菜单栏
        setJMenuBar(jmenubar); // 设置菜单栏

        // 导航菜单点击事件
        navigation.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                navigationJFrame nv = new navigationJFrame(getSonX()); // 打开导航窗口
            }

            private int getSonX() {
                return getX() + getWidth() - 14; // 获取导航窗口位置
            }
        });

        // 地点介绍菜单点击事件
        introduce.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                introduceJFrame nv = new introduceJFrame(getsonX()); // 打开地点介绍窗口
            }

            private int getsonX() {
                return getX() + getWidth() - 14; // 获取地点介绍窗口位置
            }
        });

        // 管理员端菜单点击事件
        root.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                new rootJFrame(getWidth() + getX()); // 打开管理员端窗口
            }
        });

        setVisible(true); // 设置窗体可见
    }
}

// 导航窗口类
class navigationJFrame extends JFrame {
    static String startName = ""; // 起点名称
    static String endName = ""; // 终点名称

    // 显示起点和终点
    public void showStartAndEnd() {
        MyJFrame.drawPanel.showPoints.clear(); // 清空显示点
        if (!startName.equals("")) {
            vexsinfo v = new fileUse().getVexByName(startName); // 获取起点信息
            if (v != null) {
                MyJFrame.drawPanel.showPoints.put(v.id, v); // 添加起点到显示点
            }
        }
        if (!endName.equals("")) {
            vexsinfo v1 = new fileUse().getVexByName(endName); // 获取终点信息
            if (v1 != null) {
                MyJFrame.drawPanel.showPoints.put(v1.id, v1); // 添加终点到显示点
            }
        }
        MyJFrame.drawPanel.repaint(); // 重绘面板
    }

    // 构造方法
    public navigationJFrame(int x) {
        setSize(600, 800); // 设置窗体大小
        setLocation(x, 0); // 设置窗体位置
        setTitle("导航页"); // 设置窗体标题

        JPanel panel = new JPanel(); // 创建面板
        panel.setLayout(new GridBagLayout()); // 设置布局
        panel.setBackground(new Color(245, 245, 245)); // 设置背景颜色
        GridBagConstraints gbc = new GridBagConstraints(); // 创建布局约束
        gbc.insets = new Insets(5, 5, 5, 5); // 设置内边距
        gbc.fill = GridBagConstraints.HORIZONTAL; // 设置填充方式

        JComboBox<String> startCom = new JComboBox<>(); // 创建起点下拉框
        JComboBox<String> endCom = new JComboBox<>(); // 创建终点下拉框
        JButton runStartBtn = new JButton("开始虚拟运动"); // 创建开始按钮
        JButton stopSimulationBtn = new JButton("停止虚拟运动"); // 创建停止按钮
        JButton speedUpBtn = new JButton("开启虚拟加速"); // 创建加速按钮
        JButton showHistoryBtn = new JButton("显示历史路径"); // 创建显示历史路径按钮
        JTextArea messageText = new JTextArea("已用时:00:00 , 剩余路程:0m\n当前速度:0 m/s\n你目前位于:0"); // 创建信息文本域
        messageText.setFont(new Font("黑体", Font.BOLD, 20)); // 设置字体
        messageText.setLineWrap(true); // 设置自动换行
        messageText.setEditable(false); // 设置不可编辑
        messageText.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1)); // 设置边框
        messageText.setBackground(new Color(240, 240, 240)); // 设置背景颜色

        JLabel distanceLabel = new JLabel("xxx -> yyy: 0 m"); // 创建距离标签
        distanceLabel.setFont(new Font("黑体", Font.BOLD, 18)); // 设置字体
        JLabel warnLabel = new JLabel(""); // 创建警告标签

        JButton startBtn = new JButton("查找"); // 创建起点查找按钮
        JButton endBtn = new JButton("查找"); // 创建终点查找按钮

        JLabel startLabel = new JLabel("起点:"); // 创建起点标签
        startLabel.setFont(new Font("黑体", Font.BOLD, 16)); // 设置字体
        JLabel endLabel = new JLabel("终点:"); // 创建终点标签
        endLabel.setFont(new Font("黑体", Font.BOLD, 16)); // 设置字体
        JLabel transportWayLabel = new JLabel("交通方式:"); // 创建交通方式标签
        transportWayLabel.setFont(new Font("黑体", Font.BOLD, 16)); // 设置字体

        ButtonGroup buttonGroup = new ButtonGroup(); // 创建按钮组
        JRadioButton walk = new JRadioButton("步行"); // 创建步行按钮
        JRadioButton cycling = new JRadioButton("骑行"); // 创建骑行按钮
        JRadioButton driving = new JRadioButton("驾车"); // 创建驾车按钮
        JRadioButton walkAndCycling = new JRadioButton("步行+骑行"); // 创建步行+骑行按钮
        JRadioButton walkAndDriving = new JRadioButton("步行+驾车"); // 创建步行+驾车按钮

        JLabel periodLabel = new JLabel("时间段"); // 创建时间段标签
        periodLabel.setFont(new Font("黑体", Font.BOLD, 16)); // 设置字体
        JComboBox<String> periodCom = new JComboBox<>(); // 创建时间段下拉框
        JButton optimalBtn = new JButton("查找用时最短路线"); // 创建查找用时最短路线按钮
        JButton shortestBtn = new JButton("查找距离最短路线"); // 创建查找距离最短路线按钮

        setButtonStyle(runStartBtn); // 设置按钮样式
        setButtonStyle(stopSimulationBtn); // 设置按钮样式
        setButtonStyle(speedUpBtn); // 设置按钮样式
        setButtonStyle(showHistoryBtn); // 设置按钮样式
        setButtonStyle(startBtn); // 设置按钮样式
        setButtonStyle(endBtn); // 设置按钮样式
        setButtonStyle(optimalBtn); // 设置按钮样式
        setButtonStyle(shortestBtn); // 设置按钮样式

        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 3;
        panel.add(messageText, gbc); // 添加信息文本域到面板

        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.gridwidth = 3;
        panel.add(distanceLabel, gbc); // 添加距离标签到面板

        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.gridwidth = 3;
        panel.add(warnLabel, gbc); // 添加警告标签到面板

        gbc.gridx = 0;
        gbc.gridy = 3;
        gbc.gridwidth = 1;
        panel.add(startLabel, gbc); // 添加起点标签到面板

        gbc.gridx = 1;
        gbc.gridy = 3;
        panel.add(startCom, gbc); // 添加起点下拉框到面板

        gbc.gridx = 2;
        gbc.gridy = 3;
        panel.add(startBtn, gbc); // 添加起点查找按钮到面板

        gbc.gridx = 0;
        gbc.gridy = 4;
        panel.add(endLabel, gbc); // 添加终点标签到面板

        gbc.gridx = 1;
        gbc.gridy = 4;
        panel.add(endCom, gbc); // 添加终点下拉框到面板

        gbc.gridx = 2;
        gbc.gridy = 4;
        panel.add(endBtn, gbc); // 添加终点查找按钮到面板

        gbc.gridx = 0;
        gbc.gridy = 5;
        panel.add(transportWayLabel, gbc); // 添加交通方式标签到面板

        gbc.gridx = 1;
        gbc.gridy = 5;
        panel.add(walk, gbc); // 添加步行按钮到面板

        gbc.gridx = 2;
        gbc.gridy = 5;
        panel.add(cycling, gbc); // 添加骑行按钮到面板

        gbc.gridx = 1;
        gbc.gridy = 6;
        panel.add(driving, gbc); // 添加驾车按钮到面板

        gbc.gridx = 2;
        gbc.gridy = 6;
        panel.add(walkAndCycling, gbc); // 添加步行+骑行按钮到面板

        gbc.gridx = 1;
        gbc.gridy = 7;
        panel.add(walkAndDriving, gbc); // 添加步行+驾车按钮到面板

        gbc.gridx = 0;
        gbc.gridy = 8;
        panel.add(periodLabel, gbc); // 添加时间段标签到面板

        gbc.gridx = 1;
        gbc.gridy = 8;
        panel.add(periodCom, gbc); // 添加时间段下拉框到面板

        gbc.gridx = 0;
        gbc.gridy = 9;
        gbc.gridwidth = 1;
        panel.add(optimalBtn, gbc); // 添加查找用时最短路线按钮到面板

        gbc.gridx = 1;
        gbc.gridy = 9;
        gbc.gridwidth = 1;
        panel.add(shortestBtn, gbc); // 添加查找距离最短路线按钮到面板

        gbc.gridx = 0;
        gbc.gridy = 10;
        gbc.gridwidth = 1;
        panel.add(runStartBtn, gbc); // 添加开始按钮到面板

        gbc.gridx = 1;
        gbc.gridy = 10;
        gbc.gridwidth = 1;
        panel.add(speedUpBtn, gbc); // 添加加速按钮到面板

        gbc.gridx = 2;
        gbc.gridy = 10;
        gbc.gridwidth = 1;
        panel.add(stopSimulationBtn, gbc); // 添加停止按钮到面板

        gbc.gridx = 0;
        gbc.gridy = 11;
        gbc.gridwidth = 3;
        panel.add(showHistoryBtn, gbc); // 添加显示历史路径按钮到面板

        buttonGroup.add(walk); // 将步行按钮添加到按钮组
        buttonGroup.add(cycling); // 将骑行按钮添加到按钮组
        buttonGroup.add(driving); // 将驾车按钮添加到按钮组
        buttonGroup.add(walkAndCycling); // 将步行+骑行按钮添加到按钮组
        buttonGroup.add(walkAndDriving); // 将步行+驾车按钮添加到按钮组

        startCom.addItem("选择起始位置"); // 添加起点选项
        endCom.addItem("选择终点位置"); // 添加终点选项
        MyJFrame.drawPanel.messageText = messageText; // 绑定信息文本域

        for (vexsinfo v : new fileUse().getAllVex().values()) {
            startCom.addItem(v.name); // 添加所有节点到起点下拉框
            endCom.addItem(v.name); // 添加所有节点到终点下拉框
        }

        String[] timeItem = MyJFrame.drawPanel.alg.times; // 获取时间段数组
        for (String t : timeItem) {
            periodCom.addItem(t); // 添加时间段到下拉框
        }

        // 起点查找按钮点击事件
        startBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                searchNameJFrame searchnamejframe = new searchNameJFrame(getWidth(), 0); // 打开搜索窗口
                searchnamejframe.addWindowListener(new WindowAdapter() {
                    @Override
                    public void windowClosed(WindowEvent e) {
                        super.windowClosed(e);
                        showStartAndEnd(); // 显示起点和终点
                        startCom.setSelectedItem(startName); // 选择起点
                    }
                });
            }
        });

        // 终点查找按钮点击事件
        endBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                searchNameJFrame searchnamejframe = new searchNameJFrame(getWidth(), 1); // 打开搜索窗口
                searchnamejframe.addWindowListener(new WindowAdapter() {
                    @Override
                    public void windowClosed(WindowEvent e) {
                        super.windowClosed(e);
                        showStartAndEnd(); // 显示起点和终点
                        endCom.setSelectedItem(endName); // 选择终点
                    }
                });
            }
        });

        // 起点下拉框选择事件
        startCom.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (startCom.getSelectedItem().toString().equals("选择起始位置")) {
                    startName = ""; // 清空起点名称
                    showStartAndEnd(); // 显示起点和终点
                    return;
                }
                startName = startCom.getSelectedItem().toString(); // 获取起点名称
                MyJFrame.drawPanel.shortest.clear(); // 清空最短路径
                showStartAndEnd(); // 显示起点和终点
            }
        });

        // 终点下拉框选择事件
        endCom.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (endCom.getSelectedItem().toString().equals("选择终点位置")) {
                    endName = ""; // 清空终点名称
                    showStartAndEnd(); // 显示起点和终点
                    return;
                }
                endName = endCom.getSelectedItem().toString(); // 获取终点名称
                MyJFrame.drawPanel.shortest.clear(); // 清空最短路径
                showStartAndEnd(); // 显示起点和终点
            }
        });

        // 查找用时最短路线按钮点击事件
        optimalBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                if (startCom.getSelectedItem().toString().equals("选择起始位置") || endCom.getSelectedItem().toString().equals("选择终点位置")) {
                    JOptionPane.showMessageDialog(null, "请选择起点与终点"); // 提示选择起点和终点
                    return;
                }
                messageText.setText(""); // 清空信息文本域
                distanceLabel.setText(""); // 清空距离标签
                warnLabel.setText(""); // 清空警告标签
                List<Integer> list;
                if (!walk.isSelected()) // Floyd 只针对驾车
                    list = MyJFrame.drawPanel.alg.Floyd(startCom.getSelectedItem().toString(), endCom.getSelectedItem().toString());
                else if (walkAndCycling.isSelected())
                    list = MyJFrame.drawPanel.alg.multiModeDijkstra(startCom.getSelectedItem().toString(), endCom.getSelectedItem().toString(), "步行+骑行");
                else if (walkAndDriving.isSelected())
                    list = MyJFrame.drawPanel.alg.multiModeDijkstra(startCom.getSelectedItem().toString(), endCom.getSelectedItem().toString(), "步行+驾车");
                else {
                    list = MyJFrame.drawPanel.alg.Dijkstra(startCom.getSelectedItem().toString(), endCom.getSelectedItem().toString(), "步行");
                }
                if (list == null) {
                    JOptionPane.showMessageDialog(null, "未找到有效路径"); // 提示未找到有效路径
                    return;
                }
                int s = MyJFrame.drawPanel.alg.getListIdsDistance(list); // 获取路径总距离
                if (s == 65535) {
                    JOptionPane.showMessageDialog(null, "无法到达"); // 提示无法到达
                    return;
                }
                int t = walk.isSelected() ? s / 2 : MyJFrame.drawPanel.alg.getTwoPTime(startName, endName); // 获取预计用时
                distanceLabel.setText(startName + " -> " + endName + ": " + s + "m 预计用时：" + t + "s"); // 更新距离标签
                String warn = MyJFrame.drawPanel.alg.messageCrowded(list, periodCom.getSelectedItem().toString()); // 获取拥挤信息
                warnLabel.setText(warn); // 更新警告标签
                MyJFrame.drawPanel.towPointDrawLine(list); // 绘制路径
                MyJFrame.drawPanel.repaint(); // 重绘面板
            }
        });

        // 查找距离最短路线按钮点击事件
        shortestBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                if (startCom.getSelectedItem().toString().equals("选择起始位置") || endCom.getSelectedItem().toString().equals("选择终点位置")) {
                    JOptionPane.showMessageDialog(null, "请选择起点与终点"); // 提示选择起点和终点
                    return;
                }
                messageText.setText(""); // 清空信息文本域
                distanceLabel.setText(""); // 清空距离标签
                List<Integer> shortestLoads;
                if (walk.isSelected())
                    shortestLoads = MyJFrame.drawPanel.alg.Dijkstra(startCom.getSelectedItem().toString(), endCom.getSelectedItem().toString(), "步行");
                else if (walkAndCycling.isSelected())
                    shortestLoads = MyJFrame.drawPanel.alg.multiModeDijkstra(startCom.getSelectedItem().toString(), endCom.getSelectedItem().toString(), "步行+骑行");
                else if (walkAndDriving.isSelected())
                    shortestLoads = MyJFrame.drawPanel.alg.multiModeDijkstra(startCom.getSelectedItem().toString(), endCom.getSelectedItem().toString(), "步行+驾车");
                else
                    shortestLoads = MyJFrame.drawPanel.alg.Dijkstra(startCom.getSelectedItem().toString(), endCom.getSelectedItem().toString(), "驾车");
                if (shortestLoads == null) {
                    JOptionPane.showMessageDialog(null, "无法到达"); // 提示无法到达
                    return;
                }
                MyJFrame.drawPanel.towPointDrawLine(shortestLoads); // 绘制路径
                int s = MyJFrame.drawPanel.alg.getListIdsDistance(shortestLoads); // 获取路径总距离
                String warn = MyJFrame.drawPanel.alg.messageCrowded(shortestLoads, periodCom.getSelectedItem().toString()); // 获取拥挤信息
                warnLabel.setText(warn); // 更新警告标签
                String goWay = walk.isSelected() ? "步行" : driving.isSelected() ? "驾车" : "骑行"; // 获取交通方式
                int t = MyJFrame.drawPanel.alg.getListTime(shortestLoads, goWay, periodCom.getSelectedItem().toString()); // 获取预计用时
                distanceLabel.setText(startName + " -> " + endName + ": " + s + "m 预计用时：" + t + "s"); // 更新距离标签
            }
        });

        // 开始按钮点击事件
        runStartBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                if (MyJFrame.drawPanel.shortest.isEmpty()) {
                    JOptionPane.showMessageDialog(null, "请先选择路线方式(最优或最短)"); // 提示选择路线方式
                    return;
                }
                Thread t = new Thread(MyJFrame.drawPanel); // 创建线程
                t.start(); // 启动线程
            }
        });

        // 停止按钮点击事件
        stopSimulationBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                MyJFrame.drawPanel.stopSimulation(); // 停止模拟并关闭语音播报
            }
        });


        // 加速按钮点击事件
        speedUpBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                if (MyJFrame.drawPanel.speedUp == 3) {
                    MyJFrame.drawPanel.speedUp = 1; // 还原速度
                    MyJFrame.drawPanel.every = 1; // 还原显示标签的速度信息
                    speedUpBtn.setText("开启虚拟加速"); // 更新按钮文本
                } else {
                    MyJFrame.drawPanel.speedUp = 3; // 设置速度加倍
                    MyJFrame.drawPanel.every = 1 * MyJFrame.drawPanel.speedUp; // 更新显示标签的速度信息
                    speedUpBtn.setText("停止虚拟加速"); // 更新按钮文本
                }
            }
        });

        // 驾车按钮状态改变事件
        driving.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                if (driving.isSelected()) {
                    MyJFrame.drawPanel.goWay = "驾车"; // 设置交通方式为驾车
                }
            }
        });

        // 骑行按钮状态改变事件
        cycling.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                if (cycling.isSelected()) {
                    MyJFrame.drawPanel.goWay = "骑行"; // 设置交通方式为骑行
                }
            }
        });

        // 步行+骑行按钮状态改变事件
        walkAndCycling.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                if (walkAndCycling.isSelected()) {
                    MyJFrame.drawPanel.goWay = "步行+骑行"; // 设置交通方式为步行+骑行
                }
            }
        });

        // 步行+驾车按钮状态改变事件
        walkAndDriving.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                if (walkAndDriving.isSelected()) {
                    MyJFrame.drawPanel.goWay = "步行+驾车"; // 设置交通方式为步行+驾车
                }
            }
        });

        // 显示历史路径按钮点击事件
        showHistoryBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                showHistory(); // 显示历史路径
            }
        });

        // 窗口关闭事件
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                super.windowClosing(e);
                MyJFrame.drawPanel.showPoints.clear(); // 清空显示点
                MyJFrame.drawPanel.shortest.clear(); // 清空最短路径
                MyJFrame.drawPanel.repaint(); // 重绘面板
            }
        });

        add(panel); // 添加面板到窗体
        setVisible(true); // 设置窗体可见
    }

    // 设置按钮样式
    private void setButtonStyle(JButton button) {
        button.setBackground(new Color(34, 139, 34)); // 设置背景颜色
        button.setForeground(Color.WHITE); // 设置前景颜色
        button.setFont(new Font("黑体", Font.BOLD, 16)); // 设置字体
        button.setFocusPainted(false); // 设置不绘制焦点
        button.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createLineBorder(new Color(34, 139, 34), 2), // 设置边框颜色和宽度
                BorderFactory.createEmptyBorder(5, 15, 5, 15) // 设置内边距
        ));
    }

    // 显示历史路径
    private void showHistory() {
        List<PathRecord> history = MyJFrame.drawPanel.alg.getPathHistory().getHistory(); // 获取历史路径记录
        if (history.isEmpty()) {
            JOptionPane.showMessageDialog(null, "暂无历史路径记录。"); // 提示暂无历史路径记录
            return;
        }

        JFrame historyFrame = new JFrame("历史路径记录"); // 创建历史路径记录窗体
        historyFrame.setSize(600, 400); // 设置窗体大小
        historyFrame.setLayout(new BorderLayout()); // 设置布局

        DefaultListModel<String> listModel = new DefaultListModel<>(); // 创建列表模型
        for (PathRecord record : history) {
            StringBuilder sb = new StringBuilder();
            sb.append("起点: ").append(record.getStartName())
                    .append(" -> 终点: ").append(record.getEndName())
                    .append(" | 路径: ").append(record.getPath().toString())
                    .append(" | 方式: ").append(record.getWay());
            listModel.addElement(sb.toString()); // 添加路径记录到列表模型
        }

        JList<String> historyList = new JList<>(listModel); // 创建历史路径记录列表
        historyList.setFont(new Font("黑体", Font.PLAIN, 14)); // 设置字体
        JScrollPane scrollPane = new JScrollPane(historyList); // 创建滚动面板

        historyFrame.add(scrollPane, BorderLayout.CENTER); // 添加滚动面板到窗体
        historyFrame.setVisible(true); // 设置窗体可见
    }
}

// 介绍页面类
class introduceJFrame extends JFrame {
    JList<String> nameList = new JList<>(); // 创建名称列表

    // 构造方法
    public introduceJFrame(int x) {
        setSize(550, 600); // 设置窗体大小
        setLocation(x, 0); // 设置窗体位置
        setTitle("地点介绍"); // 设置窗体标题

        JPanel panel = new JPanel(); // 创建面板
        panel.setLayout(new BorderLayout()); // 设置布局
        panel.setBackground(new Color(245, 245, 245)); // 设置背景颜色

        JTextField inputPosition = new JTextField("请输入你要搜索的地点"); // 创建输入框
        inputPosition.setFont(new Font("黑体", Font.PLAIN, 16)); // 设置字体
        inputPosition.setForeground(Color.GRAY); // 设置前景颜色
        inputPosition.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createLineBorder(Color.GRAY, 1), // 设置边框颜色和宽度
                BorderFactory.createEmptyBorder(5, 5, 5, 5) // 设置内边距
        ));
        inputPosition.addFocusListener(new FocusAdapter() {
            @Override
            public void focusGained(FocusEvent e) {
                if (inputPosition.getText().equals("请输入你要搜索的地点")) {
                    inputPosition.setText(""); // 清空输入框
                    inputPosition.setForeground(Color.BLACK); // 设置前景颜色为黑色
                }
            }

            @Override
            public void focusLost(FocusEvent e) {
                if (inputPosition.getText().isEmpty()) {
                    inputPosition.setText("请输入你要搜索的地点"); // 恢复提示文本
                    inputPosition.setForeground(Color.GRAY); // 设置前景颜色为灰色
                }
            }
        });

        JButton searchBtn = new JButton("搜索"); // 创建搜索按钮
        setButtonStyle(searchBtn); // 设置按钮样式

        JPanel searchPanel = new JPanel(new BorderLayout()); // 创建搜索面板
        searchPanel.add(inputPosition, BorderLayout.CENTER); // 添加输入框到搜索面板
        searchPanel.add(searchBtn, BorderLayout.EAST); // 添加搜索按钮到搜索面板

        nameList.setFont(new Font("黑体", Font.PLAIN, 16)); // 设置字体
        nameList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // 设置选择模式为单选
        JScrollPane scrollPane = new JScrollPane(nameList); // 创建滚动面板

        List<String> names = new fileUse().getNames(); // 获取所有名称
        DefaultListModel<String> nameListModel = new DefaultListModel<>(); // 创建列表模型
        nameListModel.addAll(names); // 添加所有名称到列表模型
        nameList.setModel(nameListModel); // 设置列表模型

        searchBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println("你的选择是" + nameList.getSelectedValue()); // 打印选择的名称
            }
        });

        nameList.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                inputPosition.setText(nameList.getSelectedValue().toString()); // 设置输入框文本为选择的名称
                vexsinfo v = new fileUse().getVexByName(nameList.getSelectedValue().toString()); // 获取节点信息
                MyJFrame.drawPanel.showPoints.clear(); // 清空显示点
                MyJFrame.drawPanel.showPoints.put(v.id, v); // 添加节点到显示点
                MyJFrame.drawPanel.repaint(); // 重绘面板
                if (e.getClickCount() == 2) { // 双击列表项
                    showPosition(nameList.getSelectedValue().toString()); // 显示节点信息
                }
            }
        });

        panel.add(searchPanel, BorderLayout.NORTH); // 添加搜索面板到主面板
        panel.add(scrollPane, BorderLayout.CENTER); // 添加滚动面板到主面板
        add(panel); // 添加主面板到窗体
        setVisible(true); // 设置窗体可见
    }

    // 显示节点信息
    private void showPosition(String name) {
        vexsinfo v = new vexsinfo(); // 创建节点对象
        for (vexsinfo vex : new fileUse().getAllVex().values()) {
            if (name.equals(vex.name)) {
                v = vex; // 获取匹配的节点信息
                break;
            }
        }
        JFrame jFrame = new JFrame(); // 创建信息窗体
        jFrame.setSize(350, 400); // 设置窗体大小
        jFrame.setLayout(new BorderLayout()); // 设置布局
        jFrame.setTitle(name); // 设置窗体标题

        JLabel title = new JLabel(name, JLabel.CENTER); // 创建标题标签
        title.setFont(new Font("黑体", Font.BOLD, 18)); // 设置字体
        title.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); // 设置边框
        jFrame.add(title, BorderLayout.NORTH); // 添加标题标签到窗体

        JTextArea jTextArea = new JTextArea(); // 创建文本域
        jTextArea.setFont(new Font("黑体", Font.PLAIN, 16)); // 设置字体
        jTextArea.setLineWrap(true); // 设置自动换行
        jTextArea.setWrapStyleWord(true); // 设置换行样式
        jTextArea.setEditable(false); // 设置不可编辑
        jTextArea.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // 设置边框
        jTextArea.append("*是否可通车: " + (v.drive == 1 ? "通" : "不通") + "\n"); // 添加是否可通车信息
        jTextArea.append("*简介:\n" + (v.introduction != null ? v.introduction : "暂无简介")); // 添加简介信息

        JScrollPane scrollPane = new JScrollPane(jTextArea); // 创建滚动面板
        scrollPane.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1)); // 设置边框
        jFrame.add(scrollPane, BorderLayout.CENTER); // 添加滚动面板到窗体

        jFrame.setVisible(true); // 设置窗体可见
    }

    // 设置按钮样式
    private void setButtonStyle(JButton button) {
        button.setBackground(new Color(34, 139, 34)); // 设置背景颜色
        button.setForeground(Color.WHITE); // 设置前景颜色
        button.setFont(new Font("黑体", Font.BOLD, 16)); // 设置字体
        button.setFocusPainted(false); // 设置不绘制焦点
        button.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createLineBorder(new Color(34, 139, 34), 2), // 设置边框颜色和宽度
                BorderFactory.createEmptyBorder(5, 15, 5, 15) // 设置内边距
        ));
    }
}

// 搜索页面类
class searchNameJFrame extends JFrame {
    vexsinfo clickV = null; // 当前选择的节点
    DefaultListModel<String> nameListModel; // 列表模型

    // 构造方法
    public searchNameJFrame(int x, int startOrEnd) {
        setSize(550, 600); // 设置窗体大小
        setLocation(x, 0); // 设置窗体位置
        setTitle("搜索页"); // 设置窗体标题

        JPanel panel = new JPanel(); // 创建面板
        panel.setLayout(new BorderLayout()); // 设置布局
        panel.setBackground(new Color(245, 245, 245)); // 设置背景颜色

        JTextField inputPosition = new JTextField("请输入你要搜索的地点"); // 创建输入框
        inputPosition.setFont(new Font("黑体", Font.PLAIN, 16)); // 设置字体
        inputPosition.setForeground(Color.GRAY); // 设置前景颜色
        inputPosition.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createLineBorder(Color.GRAY, 1), // 设置边框颜色和宽度
                BorderFactory.createEmptyBorder(5, 5, 5, 5) // 设置内边距
        ));
        inputPosition.addFocusListener(new FocusAdapter() {
            @Override
            public void focusGained(FocusEvent e) {
                if (inputPosition.getText().equals("请输入你要搜索的地点")) {
                    inputPosition.setText(""); // 清空输入框
                    inputPosition.setForeground(Color.BLACK); // 设置前景颜色为黑色
                }
            }

            @Override
            public void focusLost(FocusEvent e) {
                if (inputPosition.getText().isEmpty()) {
                    inputPosition.setText("请输入你要搜索的地点"); // 恢复提示文本
                    inputPosition.setForeground(Color.GRAY); // 设置前景颜色为灰色
                }
            }
        });

        inputPosition.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                filterList(inputPosition.getText()); // 调用过滤方法
            }
        });

        JButton searchBtn = new JButton("搜索"); // 创建搜索按钮
        setButtonStyle(searchBtn); // 设置按钮样式

        JPanel searchPanel = new JPanel(new BorderLayout()); // 创建搜索面板
        searchPanel.add(inputPosition, BorderLayout.CENTER); // 添加输入框到搜索面板
        searchPanel.add(searchBtn, BorderLayout.EAST); // 添加搜索按钮到搜索面板

        JList<String> nameList = new JList<>(); // 创建名称列表
        nameList.setFont(new Font("黑体", Font.PLAIN, 16)); // 设置字体
        nameList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // 设置选择模式为单选
        JScrollPane scrollPane = new JScrollPane(nameList); // 创建滚动面板

        List<String> names = new fileUse().getNames(); // 获取所有名称
        nameListModel = new DefaultListModel<>(); // 创建列表模型
        nameListModel.addAll(names); // 添加所有名称到列表模型
        nameList.setModel(nameListModel); // 设置列表模型

        searchBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println("你的选择是" + nameList.getSelectedValue()); // 打印选择的名称
            }
        });

        nameList.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                String selectName = nameList.getSelectedValue().toString(); // 获取选择的名称
                inputPosition.setText(selectName); // 设置输入框文本为选择的名称
                vexsinfo v = new fileUse().getVexByName(selectName); // 获取节点信息
                if (clickV != null) MyJFrame.drawPanel.showPoints.remove(clickV.id); // 移除之前选择的节点
                MyJFrame.drawPanel.showPoints.put(v.id, v); // 添加新选择的节点到显示点
                clickV = v; // 更新当前选择的节点
                MyJFrame.drawPanel.repaint(); // 重绘面板
                if (e.getClickCount() == 2) { // 双击列表项
                    if (startOrEnd == 0) navigationJFrame.startName = selectName; // 设置起点名称
                    else navigationJFrame.endName = selectName; // 设置终点名称
                    MyJFrame.drawPanel.showPoints.remove(v.id); // 移除显示点
                    dispose(); // 关闭窗口
                }
            }
        });

        panel.add(searchPanel, BorderLayout.NORTH); // 添加搜索面板到主面板
        panel.add(scrollPane, BorderLayout.CENTER); // 添加滚动面板到主面板
        add(panel); // 添加主面板到窗体
        setVisible(true); // 设置窗体可见
    }

    // 设置按钮样式
    private void setButtonStyle(JButton button) {
        button.setBackground(new Color(34, 139, 34)); // 设置背景颜色
        button.setForeground(Color.WHITE); // 设置前景颜色
        button.setFont(new Font("黑体", Font.BOLD, 16)); // 设置字体
        button.setFocusPainted(false); // 设置不绘制焦点
        button.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createLineBorder(new Color(34, 139, 34), 2), // 设置边框颜色和宽度
                BorderFactory.createEmptyBorder(5, 15, 5, 15) // 设置内边距
        ));
    }

    // 过滤列表
    private void filterList(String filterText) {
        List<String> names = new fileUse().getNames(); // 获取所有名称
        nameListModel.clear(); // 清空列表模型
        for (String name : names) {
            if (name.contains(filterText)) {
                nameListModel.addElement(name); // 添加匹配的名称到列表模型
            }
        }
    }
}
